home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / assemblers / cas.lha / fix.Z / fix / res.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-10  |  3.9 KB  |  127 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include "io.h"
  4. #include "ex.h"
  5. #include "st.h"
  6. #include "res.h"
  7.  
  8. #define R_EXTEND 0x10
  9. Item RTab; int RCur;
  10. static int RMax;
  11.  
  12. long LVal;
  13.  
  14. void ResInit(void) {
  15.    RTab = 0, RCur = RMax = 0;
  16. }
  17.  
  18. void Resolve(Item IP) {
  19.    Exp E = IP->E; byte Code; long PC; Segment Seg;
  20.    byte B, Hi, Lo, Rel; long L;
  21.    if (Phase == 1) E = EvalExp(E);
  22.    if (Phase > 0) StartLine = IP->Line, StartF = IP->File;
  23.    Code = (IP->Tag == 'Q')? 0x11: (IP->Tag == 'P')? 0x01: 0;
  24. TypeCheck:
  25.    switch (E->Tag) {
  26.       case AddrX:
  27.          Seg = SEG(E);
  28.          Rel = IP->Tag != 'R'?
  29.             Seg->Rel:
  30.             (Seg->Rel || IP->Seg->Rel) && IP->Seg != Seg;
  31.          if (Rel) goto DoMap;
  32.          L = (long)(short)Seg->Base + (long)(short)OFFSET(E);
  33.          switch (IP->Tag) {
  34.             case 'B':
  35.                if (Seg->Type != BIT) ERROR("Address type mismatch.");
  36.             break;
  37.             case 'D':
  38.                if (Seg->Type != DATA && Seg->Type != SFR)
  39.                   ERROR("Address type mismatch.");
  40.             break;
  41.             case 'R': case 'L': case 'P': case 'Q':
  42.                if (Seg->Type != CODE) ERROR("Address type mismatch.");
  43.             break;
  44.          }
  45.       break;
  46.       case NumX: L = (long)(short)VALUE(E); break;
  47.       default: goto DoMap;
  48.    }
  49. BoundsCheck:
  50.    switch (IP->Tag) {
  51.       case 'b':
  52.          if (L < -0x80 || L >= 0x100) ERROR("Byte value out of range (%4lx).", L);
  53.       break;
  54.       case 'w':
  55.          if (L < -0x8000L || L >= 0x10000L) ERROR("Word value out of range.");
  56.       break;
  57.       case 'B':
  58.          if (L < 0 || L >= 0x100) ERROR("Bit address out of range.");
  59.       break;
  60.       case 'D':
  61.          if (E->Tag != AddrX) {
  62.             if (L < 0 || L >= 0x100) ERROR("Data address out of range.");
  63.          } else if (Seg->Type == DATA) {
  64.             if (L < 0 || L >= 0x80) ERROR("Register address out of range.");
  65.          } else if (Seg->Type == SFR) {
  66.             if (L < 0x80 || L >= 0x100) ERROR("SFR address out of range.");
  67.          }
  68.       break;
  69.       case 'R':
  70.          L -= (long)(short)IP->Seg->Base + (long)(short)IP->Offset + 1L;
  71.          if (L < -0x80 || L >= 0x80) ERROR("Relative address out of range.");
  72.       break;
  73.       case 'P': case 'Q':
  74.          PC = (long)(short)IP->Seg->Base + (long)(short)IP->Offset + 2L;
  75.          if ((L&0xf800) != (PC&0xf800)) ERROR("Paged address out of range.");
  76.          L = (L << 5)&0xe000 | (Code << 8)&0x1f00 | L&0xff;
  77.       break;
  78.       case 'L':
  79.          if (L < 0 || L >= 0x10000L) ERROR("Code address out of range.");
  80.       break;
  81.       default: FATAL("Internal error (0)");
  82.    }
  83.    if (Phase == 1) {
  84.       fseek(OutF, SegTell(IP->Seg, IP->Offset), SEEK_SET); IP->Map = 0;
  85.    }
  86. Generate:
  87.    switch (IP->Tag) {
  88.       case 'b': case 'B': case 'D': case 'R':
  89.          B = L&0xff;
  90.          switch (Phase) {
  91.             case 0: PByte(B); break;
  92.             case 1: PutB(B, OutF); break;
  93.             case 2: IP->Tag = 'b', LVal = B; break;
  94.          }
  95.       return;
  96.       case 'P': case 'Q': case 'w': case 'L':
  97.          Lo = (L >> 8)&0xff, Hi = L&0xff;
  98.          switch (Phase) {
  99.             case 0: PByte(Lo), PByte(Hi); break;
  100.             case 1: PutB(Lo, OutF), PutB(Hi, OutF); break;
  101.             case 2: IP->Tag = 'w', LVal = L&0xffff; break;
  102.          }
  103.       return;
  104.    }
  105. return;
  106. DoMap:
  107.    switch (Phase) {
  108.       case 0: RCur++; L = 0; goto Generate;
  109.       case 1: IP->Map = 1; MarkExp(IP->E = E); break;
  110.       case 2: FATAL("Internal error (1).");
  111.    }
  112. }
  113.  
  114. void Reloc(byte Code, byte Tag, Exp E) {
  115.    long PC; Segment Seg; byte B; word W; long L; Item IP;
  116.    if (RCur == RMax) {
  117.       RMax += R_EXTEND, RTab = (Item)realloc(RTab, RMax * sizeof *RTab);
  118.       if (RTab == 0) FATAL("Out of memory.");
  119.    }
  120.    IP = &RTab[RCur];
  121.    IP->Tag = Tag, IP->E = E, IP->Seg = SegP, IP->Offset = LOC;
  122.    IP->Map = 0, IP->Line = StartLine, IP->File = StartF;
  123. /* ajmp: Tag = 'P', acall: Tag = 'Q' */
  124.    if (IP->Tag == 'P' && (Code&0x10)) IP->Tag = 'Q';
  125.    Resolve(IP);
  126. }
  127.